﻿using System;
using System.Text;
using SharpDX.DirectWrite;
using OpenGameEngine.Drawing;
using s = SharpDX;
using d = SharpDX.Direct2D1;

namespace OpenGameEngine.Base
{
    /// <summary>
    /// Represents a object used for drawing. This gets created on every render call.
    /// </summary>
    public class DrawEventArgs
        : GameCoreEventArgs
    {
        private bool _disposed;

        /// <summary>
        /// Gets or sets the default stroke width used by the methods, default is 1.0f
        /// </summary>
        public float StrokeWidth
        {
            get { return Globals.RenderTarget.StrokeWidth; }
            set { Globals.RenderTarget.StrokeWidth = value; }
        }

        /// <summary>
        /// Initializes a new instances of the OpenGameEngine.Base.DrawEventArgs class.
        /// </summary>
        /// <param name="core">Specify the engine it is currently using</param>
        /// <param name="time">The current time</param>
        /// <param name="target">The current render target</param>
        public DrawEventArgs(GameEngine core, GameTime time)
            : base(core, time)
        {

        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        public void DrawImage(Bitmap b, Int32 x, Int32 y)
        {
            this.DrawImage(b, (float)x, (float)y, 1f);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        public void DrawImage(Bitmap b, Int32 x, Int32 y, float opacity)
        {
            this.DrawImage(b, (float)x, (float)y, opacity);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        public void DrawImage(Bitmap b, float x, float y)
        {
            this.DrawImage(b, new RectangleF(x, y, b.Size.Width, b.Size.Height), 1f);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        public void DrawImage(Bitmap b, float x, float y, float opacity)
        {
            this.DrawImage(b, new RectangleF(x, y, b.Size.Width, b.Size.Height), opacity);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="loc">The coordinates</param>
        public void DrawImage(Bitmap b, Vector2 loc)
        {
            this.DrawImage(b, new RectangleF(loc.X, loc.Y, b.Size.Width, b.Size.Height), 1f);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="loc">The coordinates</param>
        public void DrawImage(Bitmap b, Vector2 loc, float opacity)
        {
            this.DrawImage(b, new RectangleF(loc.X, loc.Y, b.Size.Width, b.Size.Height), opacity);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="dest">The rectangle he should draw too</param>
        public void DrawImage(Bitmap b, RectangleF dest)
        {
            this.DrawImage(b, null, dest, 1f);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="dest">The rectangle he should draw too</param>
        public void DrawImage(Bitmap b, RectangleF dest, float opacity)
        {
            this.DrawImage(b, null, dest, opacity);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="opacity">The opacity of the image</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        /// <param name="source">Only this area of the bitmap is drawn</param>
        public void DrawImage(Bitmap b, float x, float y, RectangleF source, float opacity)
        {
            this.DrawImage(b, source, new RectangleF(x, y, b.Size.Width, b.Size.Height), opacity);
        }

        /// <summary>
        /// Draws a bitmap to the screen
        /// </summary>
        /// <param name="b">The bitmap to draw</param>
        /// <param name="opacity">The opacity of the image</param>
        /// <param name="source">Only this area of the bitmap is drawn</param>
        /// <param name="dest">The destination coordinates of the screen</param>
        public void DrawImage(Bitmap b, RectangleF? source, RectangleF? dest, float opacity)
        {
            if (b == null)
                throw new ArgumentNullException("b", "Make sure the Bitmap you are trying to pass isn't null");

            Globals.RenderTarget.DrawBitmap(b, dest, opacity, d.BitmapInterpolationMode.Linear, source);
        }

        /// <summary>
        /// Draws a string to the screen
        /// </summary>
        /// <param name="text">The text to draw</param>
        /// <param name="fontName">The font name</param>
        /// <param name="fontSize">The size of the font</param>
        /// <param name="brush">The brush</param>
        /// <param name="x">The x coordinates</param>
        /// <param name="y">The y coordinates</param>
        public void DrawString(String text, Font font, SolidColorBrush brush, Single x, Single y)
        {
            Int32 maxWidth = this.Core.Config.Width - 5;
            Int32 MaxHeight = this.Core.Config.Height - 5;
            DrawString(text, font, brush, new RectangleF(x, y, maxWidth, MaxHeight));
        }

        /// <summary>
        /// Draws a string to the screen
        /// </summary>
        /// <param name="text">The text to draw</param>
        /// <param name="fontName">The font name</param>
        /// <param name="fontSize">The size of the font</param>
        /// <param name="brush">The brush</param>
        /// <param name="dest">The destination coordinates</param>
        public void DrawString(String text, Font font, SolidColorBrush brush, Vector2 dest)
        {
            Int32 maxWidth = this.Core.Config.Width - 5;
            Int32 MaxHeight = this.Core.Config.Height - 5;
            DrawString(text, font, brush, new RectangleF(dest.X, dest.Y, maxWidth, MaxHeight));
        }

        /// <summary>
        /// Draws a string to the screen
        /// </summary>
        /// <param name="text">The text to draw</param>
        /// <param name="fontName">The font name</param>
        /// <param name="fontSize">The size of the font</param>
        /// <param name="brush">The brush</param>
        /// <param name="rect">The destination rectangle</param>
        public void DrawString(String text, Font font, SolidColorBrush brush, RectangleF rect)
        {
            TextFormat tf = Font.MakeFormat(font);
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.DrawText(text, tf, rect, scb);

        }

        public void DrawRectangle(Single x, Single y, Single width, Single height, SolidColorBrush brush)
        {
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.DrawRectangle(new s.RectangleF(x, y, width, height), scb);
        }

        public void DrawRectangle(RectangleF rect, SolidColorBrush brush)
        {
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.DrawRectangle(rect, scb);
        }

        public void FillRectangle(Single x, Single y, Single width, Single height, SolidColorBrush brush)
        {
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.FillRectangle(new s.RectangleF(x, y, width, height), scb);
        }

        public void FillRectangle(RectangleF rect, SolidColorBrush brush)
        {
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.FillRectangle(rect, scb);
        }

        public void DrawLine(Vector2 start, Vector2 end, SolidColorBrush brush)
        {
            DrawLine(start, end, brush, 1.0f);
        }

        public void DrawLine(Vector2 start, Vector2 end, SolidColorBrush brush, float strokeWidth)
        {
            using (d.SolidColorBrush scb = brush)
                Globals.RenderTarget.DrawLine(start, end, scb, strokeWidth);
        }
    }
}
